package com.cskaoyan.wordmemorize.service.impl;

import cn.dev33.satoken.secure.SaSecureUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cskaoyan.wordmemorize.common.constant.ResultCodeEnum;
import com.cskaoyan.wordmemorize.common.exception.BusinessException;
import com.cskaoyan.wordmemorize.converter.EmployeeConverter;
import com.cskaoyan.wordmemorize.dao.entity.*;
import com.cskaoyan.wordmemorize.dao.mapper.*;
import com.cskaoyan.wordmemorize.dto.admin.DeleteEmployeeRoleOperateDTO;
import com.cskaoyan.wordmemorize.dto.admin.EmployeeDTO;
import com.cskaoyan.wordmemorize.dto.admin.PageDTO;
import com.cskaoyan.wordmemorize.request.EmployeeCommand;
import com.cskaoyan.wordmemorize.request.PageRequest;
import com.cskaoyan.wordmemorize.service.EmployeeService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class EmployeeServiceImpl extends ServiceImpl<EmployeeMapper, EmployeeDO> implements EmployeeService {


    @Autowired
    PermissionMapper permissionMapper;
    @Autowired
    EmployeeConverter employeeConverter;
    @Autowired
    EmployeeMapper employeeMapper;
    @Autowired
    EmployeeRoleMapper employeeRoleMapper;
    @Autowired
    RoleMapper roleMapper;
    @Autowired
    RolePermissionMapper rolePermissionMapper;


    @Override
    public EmployeeDTO login(String userName, String password) {
        // 1. 查询数据库，验证后台用户的用户名和密码

        // 得到密文密码
        String passwd = SaSecureUtil.md5(password);


        LambdaQueryWrapper<EmployeeDO> employeeWrapper = new LambdaQueryWrapper<>();
        employeeWrapper.eq(EmployeeDO::getName, userName)
                .eq(EmployeeDO::getPassword, passwd);

        // 查询满足条件的员工
        EmployeeDO one = getOne(employeeWrapper);
        if (one == null) {
            throw new BusinessException(ResultCodeEnum.LOCAL_LOGIN_FAIL);
        }

        return employeeConverter.employeeDO2DTO(one);
    }

    @Override
    public EmployeeDTO getEmployeeInfo(Long employeeId) {
// 1. 查询员工基本信息
        QueryWrapper<EmployeeDO> employeeWrapper = new QueryWrapper<>();
        employeeWrapper.eq("id", employeeId).eq("is_deleted", 0);
        EmployeeDO employeeDO = employeeMapper.selectOne(employeeWrapper);
        if (employeeDO == null) {
            return null;
        }

        // 转换DTO并清空密码
        EmployeeDTO employeeDTO = new EmployeeDTO();
        BeanUtils.copyProperties(employeeDO, employeeDTO);
        employeeDTO.setPassword(null); // 清空密码
        employeeDTO.setId(employeeDO.getId().toString()); // 转换ID为String

        // 2. 查询员工角色ID列表
        QueryWrapper<EmployeeRoleDO> roleWrapper = new QueryWrapper<>();
        roleWrapper.select("role_id")
                .eq("employee_id", employeeId)
                .eq("is_deleted", 0);
        List<Long> roleIds = employeeRoleMapper.selectList(roleWrapper)
                .stream()
                .map(EmployeeRoleDO::getRoleId)
                .collect(Collectors.toList());

        // 3. 如果没有角色直接返回
        if (CollectionUtils.isEmpty(roleIds)) {
            employeeDTO.setPerms(Collections.emptyList());
            return employeeDTO;
        }

        // 4. 查询角色对应的权限ID
        QueryWrapper<RolePermissionDO> rpWrapper = new QueryWrapper<>();
        rpWrapper.select("permission_id")
                .in("role_id", roleIds)
                .eq("is_deleted", 0);
        List<Long> permissionIds = rolePermissionMapper.selectList(rpWrapper)
                .stream()
                .map(RolePermissionDO::getPermissionId)
                .distinct()
                .collect(Collectors.toList());

        // 5. 查询权限码
        if (CollectionUtils.isEmpty(permissionIds)) {
            employeeDTO.setPerms(Collections.emptyList());
            return employeeDTO;
        }

        QueryWrapper<PermissionDO> permWrapper = new QueryWrapper<>();
        permWrapper.select("permission_code")
                .in("id", permissionIds)
                .eq("is_deleted", 0);
        List<String> perms = permissionMapper.selectList(permWrapper)
                .stream()
                .map(PermissionDO::getPermissionCode)
                .collect(Collectors.toList());

        employeeDTO.setPerms(perms);
        return employeeDTO;
    }

    @Override
    public PageDTO<EmployeeDTO> getEmployeePage(PageRequest request) {
        // 处理分页参数
        int pageNum = request.getPageNum() != null ? request.getPageNum() : 1;
        int pageSize = request.getCount() != null ? request.getCount() : 10;

        // 构建查询条件
        QueryWrapper<EmployeeDO> wrapper = new QueryWrapper<>();
        wrapper.eq("is_deleted", 0); // 只查询未删除的记录

        // 关键词查询（姓名或电话）
        if (StringUtils.isNotBlank(request.getKeyword())) {
            wrapper.and(w -> w.like("name", request.getKeyword())
                    .or()
                    .like("phone_number", request.getKeyword()));
        }

        // 执行分页查询
        Page<EmployeeDO> page = new Page<>(pageNum, pageSize);
        Page<EmployeeDO> doPage = employeeMapper.selectPage(page, wrapper);

        // 批量获取员工角色映射
        List<Long> employeeIds = doPage.getRecords().stream()
                .map(EmployeeDO::getId)
                .collect(Collectors.toList());
        Map<Long, List<Long>> roleMap = new HashMap<>();

        if (!employeeIds.isEmpty()) {
            QueryWrapper<EmployeeRoleDO> roleWrapper = new QueryWrapper<>();
            roleWrapper.in("employee_id", employeeIds)
                    .eq("is_deleted", 0);
            List<EmployeeRoleDO> roles = employeeRoleMapper.selectList(roleWrapper);

            // 构建员工ID->角色ID列表的映射
            for (EmployeeRoleDO role : roles) {
                roleMap.computeIfAbsent(role.getEmployeeId(), k -> new ArrayList<>())
                        .add(role.getRoleId());
            }
        }

        // 设置角色ID并转换DTO
        List<EmployeeDTO> dtoList = doPage.getRecords().stream().map(employee -> {
            employee.setRoleIds(roleMap.getOrDefault(employee.getId(), Collections.emptyList()));
            EmployeeDTO dto = employeeConverter.employeeDO2DTO(employee);  // 先转换
            dto.setPassword(null);  // 显式清空密码
            return dto;
        }).collect(Collectors.toList());

        // 构建分页结果
        PageDTO<EmployeeDTO> result = new PageDTO<>();
        result.setPageList(dtoList);
        result.setTotalCount(doPage.getTotal());

        return result;
    }

    @Override
    @Transactional
    public void addEmployee(EmployeeCommand command) {

        // 2. 创建EmployeeDO对象并填充数据
        EmployeeDO employee = new EmployeeDO();
        employee.setName(command.getName());
        employee.setNickName(command.getNickName());
        employee.setPhoneNumber(command.getPhoneNumber());

        // 使用SaToken的MD5加密密码
        employee.setPassword(SaSecureUtil.md5(command.getPassword()));

        employee.setAvatar(command.getAvatar());
        // 其他字段由数据库默认值填充
        employeeMapper.insert(employee);
        Long employeeId = employee.getId();

        // 3. 处理角色关联数据（单条插入）
        if (command.getRoleIds() != null && !command.getRoleIds().isEmpty()) {
            for (String roleIdStr : command.getRoleIds()) {
                Long roleId = Long.parseLong(roleIdStr);

                EmployeeRoleDO relation = new EmployeeRoleDO();
                relation.setRoleId(roleId);
                relation.setEmployeeId(employeeId);

                // 使用MybatisPlus的insert方法单条插入
                employeeRoleMapper.insert(relation);
            }
        }
    }

    @Override
    @Transactional
    public void updateEmployee(EmployeeCommand command) {
        // 1. 验证输入参数
        if (command.getId() == null) {
            throw new IllegalArgumentException("员工ID不能为空");
        }

        Long employeeId = Long.parseLong(command.getId());

        // 2. 更新员工基本信息
        EmployeeDO employee = employeeMapper.selectById(employeeId);
        if (employee == null) {
            throw new RuntimeException("员工不存在，ID: " + employeeId);
        }

        // 更新可修改的字段
        employee.setName(command.getName());
        employee.setNickName(command.getNickName());
        employee.setPhoneNumber(command.getPhoneNumber());
        employee.setAvatar(command.getAvatar());

        // 如果提供了新密码，则更新密码
        if (StringUtils.isNotBlank(command.getPassword())) {
            employee.setPassword(SaSecureUtil.md5(command.getPassword()));
        }

        // 使用MybatisPlus更新员工记录
        employeeMapper.updateById(employee);

        // 3. 更新员工角色关系
        if (command.getRoleIds() != null) {
            // 先删除该员工所有现有角色关联（逻辑删除）
            UpdateWrapper<EmployeeRoleDO> deleteWrapper = new UpdateWrapper<>();
            deleteWrapper.set("is_deleted", 1) // 逻辑删除标志
                    .set("updated_time", new Date()) // 更新时间
                    .eq("employee_id", employeeId)
                    .eq("is_deleted", 0); // 只处理未删除的记录

            employeeRoleMapper.update(null, deleteWrapper);

            // 如果提供了新角色列表，则添加新角色关联
            if (!command.getRoleIds().isEmpty()) {
                for (String roleIdStr : command.getRoleIds()) {
                    Long roleId = Long.parseLong(roleIdStr);

                    // 检查角色是否存在（可选）
                    // RoleDO role = roleMapper.selectById(roleId);
                    // if (role == null) {
                    //     throw new RuntimeException("角色不存在，ID: " + roleId);
                    // }

                    // 创建新角色关联
                    EmployeeRoleDO newRelation = new EmployeeRoleDO();
                    newRelation.setEmployeeId(employeeId);
                    newRelation.setRoleId(roleId);
                    newRelation.setIsDeleted(0); // 设置为未删除

                    employeeRoleMapper.insert(newRelation);
                }
            }
        }
    }

    @Transactional
    @Override
    public void delete(Long employeeId) {
        // 1. 验证员工ID
        if (employeeId == null) {
            throw new IllegalArgumentException("员工ID不能为空");
        }

        // 2. 验证员工存在性
        EmployeeDO employee = employeeMapper.selectById(employeeId);
        if (employee == null || employee.getIsDeleted() == 1) {
            throw new RuntimeException("员工不存在或已被删除，ID: " + employeeId);
        }

        // 3. 逻辑删除员工记录
        UpdateWrapper<EmployeeDO> employeeWrapper = new UpdateWrapper<>();
        employeeWrapper.set("is_deleted", 1)
                .set("updated_time", new Date()) // 使用当前时间作为更新时间
                .eq("id", employeeId)
                .eq("is_deleted", 0); // 只更新未删除的记录

        int employeeUpdateCount = employeeMapper.update(null, employeeWrapper);

        if (employeeUpdateCount == 0) {
            throw new RuntimeException("员工删除失败，可能已被删除，ID: " + employeeId);
        }

        // 4. 逻辑删除员工的所有角色关联
        UpdateWrapper<EmployeeRoleDO> roleWrapper = new UpdateWrapper<>();
        roleWrapper.set("is_deleted", 1)
                .set("updated_time", new Date()) // 使用当前时间作为更新时间
                .eq("employee_id", employeeId)
                .eq("is_deleted", 0); // 只更新未删除的记录

        employeeRoleMapper.update(null, roleWrapper);
    }

    @Override
    public DeleteEmployeeRoleOperateDTO deleteRole(Long employeeId, Long roleId) {
        QueryWrapper<EmployeeRoleDO> relationWrapper = new QueryWrapper<>();
        relationWrapper.eq("employee_id", employeeId)
                .eq("role_id", roleId);

        // 2. 查询员工信息（即使员工已被删除也获取历史数据）
        EmployeeDO employee = employeeMapper.selectById(employeeId);

        // 3. 查询角色信息（即使角色已被删除也获取历史数据）
        RoleDO role = roleMapper.selectById(roleId);

        UpdateWrapper<EmployeeRoleDO> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("employee_id", employeeId)
                .eq("role_id",roleId)
                .set("is_deleted", 0);

        employeeRoleMapper.update(null, updateWrapper);

        // 5. 构建返回DTO
        DeleteEmployeeRoleOperateDTO dto = new DeleteEmployeeRoleOperateDTO();
        dto.setEmployeeId(employeeId);
        dto.setEmployeeName(employee != null ? employee.getName() : "未知员工");
        dto.setRoleId(String.valueOf(roleId)); // 转换为String类型
        dto.setRoleName(role != null ? role.getName() : "未知角色");

        return dto;
    }

    @Override
    public void updateLoginInfo(Long employeeId, String ip, LocalDateTime time) {

    }

    @Override
    public Set<String> getPermissionAlias(Long employeeId) {
        return null;
    }
}
